﻿#define _CRT_SECURE_NO_WARNINGS 1

///操作符
//原码，反码，补码
//原码
//有符号的整数二进制中，最高位为符号位，其他全为数值位。
//原码：直接将数值翻译成二进制就是原码
//反码：符号位不变，其他对原码按位取反
//补码：反码+1就得到补码
//对于整形来说，数据存放在内存中实际上是补码


//4.移位操作符
//<<左移操作符
//>>右移操作符
//Remark：移位操作符的操作数只能是整数
//4.1 左移操作符
//移位规则：左边抛弃，右边补零(操作的字节数为操作对象的字节数)
//#include<stdio.h>
//int main()
//{
//	int num = 10;
//	int n = num << 1;
//	printf("%d\n", num);
//	printf("%d\n", n);
//	return 0;
//}

//4.2右移操作符
//移位规则:两种
//1：逻辑右移：左边用零填充，右边丢弃
//2：算数右移：左边用原该值的符号位填充，右边丢弃

//#include <stdio.h>
//int main()
//{
//	int num = 10;
//	int n = num >> 1;
//	printf("n= %d\n", n);
//	printf("num= %d\n", num);
//	return 0;
//}

//remark 不能移动负数位，即不存在<<-1或>>-1;
//那么什么时候右移是逻辑右移，什么时候是算数右移
//猜测：当正数时时逻辑右移，负数时是算术右移；但统一一下，可以都理解为算数右移；


//位操作符
//& | ^ ~
//& 按位与 可以理解为and
//|  按位或 可以理解为or
// ^ 按位异或 可以理解为 EXO  当两个对应的二进制位相同时，结果为0；当两个对应的二进制位不同时，结果为1。
// ~ 按位取反 就是二进制位取反
//#include <stdio.h>
//int main()
//{
//	int num1 = -3;
//	int num2 = 5;
//	printf("%d\n", num1 & num2);
//	printf("%d\n", num1 | num2);
//	printf("%d\n", num1 ^ num2);
//	printf("%d\n", ~0);
//	return 0;
//}


//不能创建临时变量，实现两个数的交换。
//#include<stdio.h>
//int main()
//{
//	int a = 1;
//	int b = 5;
//	b = a ^ b;
//	a = a ^ b;
//	b = a ^ b;
//	printf("%d,%d", a, b);
//	return 0;
//}


//练习一
//编写代码实现：求一个整数存储在内存中二进制中一的个数


//方法一：

//#include<stdio.h>
//int main()
//{
//	int m = 1999;
//	int n = 2299;
//	int num = m^n;
//	int count = 0;
//	while (num)
//	{
//		count++;
//		num = num & (num - 1);
//	}
//	printf("%d", count);
//	return 0;
//}


//方法二

//#include<stdio.h>
//int main()
//{
//	int num = -1;
//	int i = 0;
//	int count = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if (num & (1 << i))
//			count++;
//	}
//	printf("%d", count);
//	return 0;
//}
//
//


//编写代码将13⼆进制序列的第5位修改为1，然后再改回0
//#include<stdio.h>
//int main()
//{
//	int num = 13;
//	num = num | (1 << 4);
//	printf("num=%d\n", num);
//	num = num & ~(1 << 4);
//	printf("num=%d\n", num);
//
//	return 0;
//}



//单目操作符
//！ ++ -- & * + - ~ sizeof 
//单目操作符的特点是只有一个操作数。


//逗号表达式
//exp1, exp2, exp3, expN;
//逗号表达式顾名思义就是有逗号隔开的多个表达式
//逗号表达式，从左往右依次执行。整个表达式的结果是最后一个表达式的结果。


//下标访问、函数调用
//[]下标引用操作符
//函数调用操作符


//结构成员访问操作符
//结构体 struct 

//结构体成员访问操作符
//结构体成员直接访问
//结构体成员的直接访问是通过点操作符（.）访问的
//使用方式：结构体变量.成员名
//结构体成员的间接访问
//有时候我们得到的不是一个结构体变量，而是得到了一个指向结构体的指针
//#include <stdio.h>
//struct Point
//{
//	int x;
//	int y;
//};
//int main()
//{
//	struct Point p = { 3, 4 };
//	struct Point* ptr = &p;
//	ptr->x = 10;
//	ptr->y = 20;
//	printf("x = %d y = %d\n", ptr->x, ptr->y);
//	return 0;
//}


//操作符的属性：优先级、结合性
//圆括号（ () ）
//• ⾃增运算符（ ++ ），⾃减运算符（ -- ）
//• 单⽬运算符（ + 和 - ）
//• 乘法（ * ），除法（ / ）
//• 加法（ + ），减法（ - ）
//• 关系运算符（ < 、 > 等）
//• 赋值运算符（ = ）
//由于圆括号的优先级最⾼，可以使⽤它改变其他运算符的优先级。

//表达式求值
//整形提升

//表达式4
//#include<stdio.h>
//
//int fun()
//{
//	static int count = 1;
//	return ++count;
//}
//
//int main()
//{
//	int answer;
//	answer = fun() - fun() * fun();
//	printf("%d\n", answer);//输出多少？
//	return 0;
//}

//这个代码有没有实际的问题？有问题！
//虽然在大多数的编译器上求得结果都是相同的。
//但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知：先
//算乘法，再算减法。
//函数的调⽤先后顺序⽆法通过操作符的优先级确定。实际顺序还是从左往右


//在一个整型数组中，只有一个数字出现一次，其他数组都是成对出现的，请找出那个只出现一次的数字。
//例如：
//数组中有：1 2 3 4 5 1 2 3 4，只有5出现一次，其他数字都出现2次，找出5
//#define N 11
//#include<stdio.h>
//int main()
//{
//	int arr[N] = { 1,2,3,4,6,1,2,3,4,6,9 };
//	int result = 0;
//	for (int i = 0; i < N; i++) {
//		result ^= arr[i];
//	}
//	printf("%d\n", result);
//	return 0;
//}


//打印整数二进制的奇数位和偶数位
//获取一个整数二进制序列中所有的偶数位和奇数位，分别打印出二进制序列
#include<stdio.h>
int arr1[32];

int main()
{
	int m = -1;
	for (int i = 0; i < 32; i++)
	{
		arr1[i]= (m>> i) & 1;
	}
	printf("奇数为：\n");
	for (int i = 31; i >= 0; i -= 2)
	{
		printf("%d", arr1[i]);
	}
	printf("\n");
	printf("偶数为：\n");
	for (int i = 30; i >= 0; i -= 2)
	{
		printf("%d", arr1[i]);
	}
	return 0;
}